package com.qding.park.manager.app.queue.handle;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;

import com.qding.park.common.core.cache.service.CacheServiceFacade;
import com.qding.park.common.core.constant.MongodbConstant;
import com.qding.park.common.core.exceptions.BaseException;
import com.qding.park.common.core.exceptions.IExceptionHandle;
import com.qding.park.manager.app.queue.config.QueueTaskHandleConfig;
import com.qding.park.manager.pojo.queue.QueueMsg;
import com.qding.park.manager.pojo.queue.QueueTaskDiscardlLog;

/**
 * @ClassName: AbstractHandle
 * @Description: 抽象类
 * @author Comsys-Administrator
 * @date 2016年10月29日 下午2:43:00
 *
 */
public abstract class AbstractHandle implements IHandle {

	protected static final Log _log = LogFactory.getLog(AbstractHandle.class);
	

	@Autowired
	private IExceptionHandle exceptionHandle;

	/**
	 * @Fields cacheServiceFacade : TODO（缓存操作）
	 */
	@Autowired
	protected CacheServiceFacade cacheServiceFacade;

	@Autowired
	protected MongoTemplate mongoTemplate;

//	private static final int failNum = 10;

	/**
	 * actualHandle(实际外理方法)
	 *
	 * @Title: actualHandle @Description: TODO @param @param msg 设定文件 @return
	 *         void 返回类型 @throws
	 */
	abstract void actualHandle(QueueMsg msg) throws BaseException;

	/**
	 * @param msg
	 *            任备消息体
	 * @return 任务失败并且丢弃   业务回滚方法
	 */
	abstract boolean failDiscardRollBacK(QueueMsg msg);

	protected void exceptionHandle(QueueMsg msg, String queue_name) {
		try {
			if (msg.getSerail() < QueueTaskHandleConfig.getRetry_times()) {
				// 继续重试
				msg.setSerail(msg.getSerail() + 1);
				// 重新入队
				cacheServiceFacade.msg_queue_push(msg, queue_name);

				Thread.sleep(1000 * QueueTaskHandleConfig.getRetry_sleep_seconds());
			} else if (msg.getSerail() >= QueueTaskHandleConfig.getRetry_times() && msg.getFailNum() <=QueueTaskHandleConfig.getAllow_fail_num()) {
				// 不重试了,重新入mongodb队列
				String queueMsgFail = MongodbConstant.TABLENAME_QUEUEMSG_FAIL;
				msg.setFailNum(msg.getFailNum()+1);
				mongoTemplate.insert(msg, queueMsgFail);
			} else if (msg.getSerail() >= QueueTaskHandleConfig.getRetry_times() && msg.getFailNum() > QueueTaskHandleConfig.getAllow_fail_num()) {
				// 丢弃的任务
				msg.setFailNum(msg.getFailNum()+1);
				discardTask(msg);
			}

		} catch (Exception e) {
			exceptionHandle.handle(e);
		}
	}

	/**
	 * @param msg
	 *            处理丢弃的任务
	 */
	private void discardTask(QueueMsg msg) {
		try {
			QueueTaskDiscardlLog discardLog = new QueueTaskDiscardlLog();
			discardLog.setQueueMsg(msg);
			if (failDiscardRollBacK(msg)) {
				// 回滚成功
				discardLog.setRollBacKResult(QueueTaskDiscardlLog.ROLL_BACK_SUCCESS);
			} else {
				// 回滚失败
				discardLog.setRollBacKResult(QueueTaskDiscardlLog.ROLL_BACK_FAIL);
			}
			mongoTemplate.insert(discardLog, MongodbConstant.TABLENAME_Discard_TASK);
		} catch (Throwable e) {
			exceptionHandle.handle(e);
			_log.error("回滚丢弃任务记录日志异常:"+msg);
		}

	}
}
